﻿using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization.Formatters.Soap;
using System.Xml.Serialization;
using FNN.CustomFunctions;
using FNN.NetworkComponents;
using FNN.Networks;
using System;
using Newtonsoft.Json;

namespace FNN.Helpers
{
    public class SerializationHelper
    {
        public T ParseJson<T>(string filePath)
        {
            T result;
            var deserializer = new JsonSerializer();
            using (StreamReader streamReader = new StreamReader(filePath))
            using (JsonTextReader reader = new JsonTextReader(streamReader))
            {
                result = deserializer.Deserialize<T>(reader);
            }
            return result;
        }

        /// <summary>
        ///     Сохранение в бинарный формат
        /// </summary>
        /// <param name="objGraph">Сериализуемый объект</param>
        /// <param name="filePath">Путь к файлу</param>
        public void WriteBinary(Network objGraph, string filePath)
        {
            var binaryFormatter = new BinaryFormatter();
            using (Stream fStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
            {
                binaryFormatter.Serialize(fStream, objGraph);
            }
        }

        /// <summary>
        ///     Загрузить из бинарного файла
        /// </summary>
        /// <param name="filePath">Путь к файлу</param>
        /// <returns>Сеть</returns>
        public Network LoadBinary(string filePath)
        {
            var binFormatter = new BinaryFormatter();

            using (Stream fStream = File.OpenRead(filePath))
            {
                try
                {
                    var networkFromDisk =
                        (Network)binFormatter.Deserialize(fStream);
                    return networkFromDisk;
                }
                catch
                {
                    return null;
                }
            }
        }

        /// <summary>
        ///     Записать в файл SOAP
        /// </summary>
        /// <param name="objGraph">Сериализуемый объект</param>
        /// <param name="filePath">Путь к файлу</param>
        public void WriteSoap(Network objGraph, string filePath)
        {
            var soapFormatter = new SoapFormatter();
            using (Stream fStream = new FileStream(filePath,
                FileMode.Create, FileAccess.Write, FileShare.None))
            {
                soapFormatter.Serialize(fStream, objGraph);
            }
        }

        /// <summary>
        ///     Загрузить из файла SOAP
        /// </summary>
        /// <param name="filePath">Путь к файлу</param>
        /// <returns>Сеть</returns>
        public Network LoadSoap(string filePath)
        {
            var soapFormatter = new SoapFormatter();

            using (Stream fStream = File.OpenRead(filePath))
            {
                try
                {
                    var networkFromDisk =
                        (Network)soapFormatter.Deserialize(fStream);
                    return networkFromDisk;
                }
                catch
                {
                    return null;
                }
            }
        }

        /// <summary>
        ///     Записать в XML
        /// </summary>
        /// <param name="objGraph">Сериализуемый объект</param>
        /// <param name="filePath">Путь к файлу</param>
        public void WriteXml(Network objGraph, string filePath)
        {
            var xmlFormatter = new XmlSerializer(typeof(Network),
                new[] { typeof(Layer), typeof(Synapse), typeof(Neuron), typeof(Linear), typeof(Sigmoid), typeof(SimpleFractional), typeof(HyperboleTangent), typeof(Sinus), typeof(BipolarSigmoid) });
            using (Stream fStream = new FileStream(filePath,
                FileMode.Create, FileAccess.Write, FileShare.None))
            {
                xmlFormatter.Serialize(fStream, objGraph);
            }
        }

        /// <summary>
        ///     Загрузить из XML
        /// </summary>
        /// <param name="filePath">Путь к файлу</param>
        /// <returns>Сеть</returns>
        public Network LoadXml(string filePath)
        {
            var xmlFormatter = new XmlSerializer(typeof(Network),
                new[] { typeof(Layer), typeof(Synapse), typeof(Neuron), typeof(Linear), typeof(Sigmoid), typeof(SimpleFractional), typeof(HyperboleTangent), typeof(Sinus), typeof(BipolarSigmoid) });

            using (Stream fStream = File.OpenRead(filePath))
            {
                try
                {
                    var networkFromDisk =
                        (Network)xmlFormatter.Deserialize(fStream);
                    return networkFromDisk;
                }
                catch
                {
                    return null;
                }
            }
        }
    }
}
